package com.meihuayishu.backend.util;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;

/**
 * 增强版真太阳时计算器
 * 提供更精确的真太阳时计算和缓存机制
 */
@Component
public class EnhancedSolarTimeCalculator {
    
    // 中国标准时间的经度（东经120度）
    private static final double CHINA_STANDARD_LONGITUDE = 120.0;
    
    // 城市经度缓存
    private final Map<String, Double> cityLongitudeCache = new HashMap<>();
    
    // 太阳时偏差缓存（日期+经度 -> 偏差分钟）
    private final Map<String, Integer> solarTimeOffsetCache = new HashMap<>();
    
    public EnhancedSolarTimeCalculator() {
        initCityLongitudes();
    }
    
    /**
     * 初始化主要城市经度数据
     */
    private void initCityLongitudes() {
        cityLongitudeCache.put("北京", 116.4);
        cityLongitudeCache.put("上海", 121.5);
        cityLongitudeCache.put("广州", 113.3);
        cityLongitudeCache.put("深圳", 114.1);
        cityLongitudeCache.put("成都", 104.1);
        cityLongitudeCache.put("杭州", 120.2);
        cityLongitudeCache.put("武汉", 114.3);
        cityLongitudeCache.put("西安", 108.9);
        cityLongitudeCache.put("重庆", 106.5);
        cityLongitudeCache.put("南京", 118.8);
        cityLongitudeCache.put("天津", 117.2);
        cityLongitudeCache.put("苏州", 120.6);
        cityLongitudeCache.put("郑州", 113.6);
        cityLongitudeCache.put("长沙", 113.0);
        cityLongitudeCache.put("沈阳", 123.4);
        cityLongitudeCache.put("青岛", 120.4);
        cityLongitudeCache.put("大连", 121.6);
        cityLongitudeCache.put("宁波", 121.6);
        cityLongitudeCache.put("厦门", 118.1);
        cityLongitudeCache.put("福州", 119.3);
        cityLongitudeCache.put("哈尔滨", 126.5);
        cityLongitudeCache.put("济南", 117.0);
        cityLongitudeCache.put("长春", 125.3);
        cityLongitudeCache.put("昆明", 102.7);
        cityLongitudeCache.put("合肥", 117.2);
        cityLongitudeCache.put("南宁", 108.3);
        cityLongitudeCache.put("太原", 112.5);
        cityLongitudeCache.put("石家庄", 114.5);
        cityLongitudeCache.put("乌鲁木齐", 87.6);
        cityLongitudeCache.put("拉萨", 91.1);
    }
    
    /**
     * 计算真太阳时偏差（分钟）
     * @param dateTime 日期时间
     * @param longitude 经度
     * @return 真太阳时偏差（分钟）
     */
    public int calculateSolarTimeOffset(LocalDateTime dateTime, double longitude) {
        // 生成缓存键
        String cacheKey = dateTime.toLocalDate().toString() + ":" + longitude;
        
        // 检查缓存
        if (solarTimeOffsetCache.containsKey(cacheKey)) {
            return solarTimeOffsetCache.get(cacheKey);
        }
        
        // 计算经度偏差导致的时间差（每经度4分钟）
        double longitudeOffset = (longitude - CHINA_STANDARD_LONGITUDE) * 4;
        
        // 计算日期方程（简化版）
        int dayOfYear = dateTime.getDayOfYear();
        double equationOfTime = calculateEquationOfTime(dayOfYear);
        
        // 总偏差（分钟）
        int offset = (int) Math.round(longitudeOffset + equationOfTime);
        
        // 缓存结果（30分钟有效期，这里简化处理，实际应该有定时清理机制）
        solarTimeOffsetCache.put(cacheKey, offset);
        
        return offset;
    }
    
    /**
     * 计算日期方程（改进版）
     * @param dayOfYear 一年中的第几天
     * @return 日期方程值（分钟）
     */
    private double calculateEquationOfTime(int dayOfYear) {
        // 改进的日期方程计算，更精确
        double b = 2 * Math.PI * (dayOfYear - 81) / 365.0;
        return 9.87 * Math.sin(2 * b) - 7.53 * Math.cos(b) - 1.5 * Math.sin(b);
    }
    
    /**
     * 根据出生地经度调整时间
     * @param dateTime 原始日期时间
     * @param birthLocation 出生地（格式：城市名或经度值）
     * @return 调整后的日期时间
     */
    public LocalDateTime adjustTimeByLocation(LocalDateTime dateTime, String birthLocation) {
        // 获取经度
        double longitude = extractLongitude(birthLocation);
        
        // 计算偏差（分钟）
        int offsetMinutes = calculateSolarTimeOffset(dateTime, longitude);
        
        // 调整时间
        return dateTime.plusMinutes(offsetMinutes);
    }
    
    /**
     * 从位置信息中提取经度
     * @param location 位置信息
     * @return 经度值
     */
    public double extractLongitude(String location) {
        if (location == null || location.isEmpty()) {
            return CHINA_STANDARD_LONGITUDE;
        }
        
        // 检查是否是城市名
        if (cityLongitudeCache.containsKey(location)) {
            return cityLongitudeCache.get(location);
        }
        
        // 尝试直接解析为经度值
        try {
            return Double.parseDouble(location);
        } catch (NumberFormatException e) {
            // 如果不是数字，返回默认经度
            return CHINA_STANDARD_LONGITUDE;
        }
    }
    
    /**
     * 添加城市经度数据
     * @param city 城市名
     * @param longitude 经度
     */
    public void addCityLongitude(String city, double longitude) {
        cityLongitudeCache.put(city, longitude);
    }
    
    /**
     * 清除太阳时偏差缓存
     */
    public void clearSolarTimeOffsetCache() {
        solarTimeOffsetCache.clear();
    }
}